package com.jumi.microservice.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jumi.microservice.common.constant.ResultEnum;
import com.jumi.microservice.common.exception.BaseException;
import com.jumi.microservice.common.exception.BusinessException;
import com.jumi.microservice.constant.ExceptionEnum;
import com.jumi.microservice.constant.IResponseRxceptionCode;
import com.jumi.microservice.constant.NumberConstant;
import com.jumi.microservice.constant.StatusEnum;
import com.jumi.microservice.domain.dto.RoleDTO;
import com.jumi.microservice.domain.AccountRoleRelationship;
import com.jumi.microservice.domain.Role;
import com.jumi.microservice.domain.RolePriorityRelationship;
import com.jumi.microservice.mapper.AccountRoleRelationshipMapper;
import com.jumi.microservice.mapper.RoleMapper;
import com.jumi.microservice.mapper.RolePriorityRelationshipMapper;
import com.jumi.microservice.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author liuz
 * @since 2020-07-18
 */
@Service
@Transactional
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {

    @Autowired
    RolePriorityRelationshipMapper rolePriorityRelationshipMapper;

    @Autowired
    AccountRoleRelationshipMapper accountRoleRelationshipMapper;

    /**
     *  新增角色
     * @param vo 角色信息
     */
    @Override
    public void insert(RoleDTO vo) {
        Role r = dto2Po(vo);
        ExceptionEnum.FAIL_NULL.doThrowIf(r==null);
        //判断角色名称唯一
        int count = baseMapper.selectCount(
                Wrappers.<Role>lambdaQuery()
                        .eq(Role::getRoleName,r.getRoleName()));
        ExceptionEnum.FAIL_ROLES_RXIST.doThrowIf(count>NumberConstant.NUMBER_ZERO);
        r.setCreateTime(LocalDateTime.now());
        r.setUpdateTime(LocalDateTime.now());
        //保存角色信息
        baseMapper.insert(r);
        //获取绑定的权限信息
        List<Integer> priortys = vo.getPriorityIds();
        if(priortys!=null&&priortys.size()>NumberConstant.NUMBER_ZERO){
            //保存角色权限绑定关系
            savePrioirs(priortys,r.getId());
        }
    }

    /**
     * 获取角色信息
     * @param id 主键id
     * @return
     */
    @Override
    public RoleDTO selectById(Long id) {
        ExceptionEnum.FAIL_ID_NULL.doThrowIf(id==null);
        Role r = baseMapper.selectById(id);
        ExceptionEnum.FAIL_NULL.doThrowIf(r==null);
        RoleDTO vo = po2Dto(r);
        List<Object> priIds = rolePriorityRelationshipMapper.selectObjs(
                Wrappers.<RolePriorityRelationship>lambdaQuery()
                        .select(RolePriorityRelationship::getPriorityId)
                        .eq(RolePriorityRelationship::getRoleId,id));
        if(priIds.size()>NumberConstant.NUMBER_ZERO){
            List<Integer> ids = (List<Integer>)(List) priIds;
            vo.setPriorityIds(ids);
        }
        return vo;
    }

    /**
     * 更新角色
     * @param vo 角色信息
     */
    @Override
    public void updateRole(RoleDTO vo) {
        Role r = dto2Po(vo);
        ExceptionEnum.FAIL_NULL.doThrowIf(r==null||r.getId()==null);
        r.setUpdateTime(LocalDateTime.now());
        //判断角色名称唯一
        int count = baseMapper.selectCount(
                Wrappers.<Role>lambdaQuery()
                        .eq(Role::getRoleName,r.getRoleName())
                        .ne(Role::getId,r.getId()));
        ExceptionEnum.FAIL_ROLES_RXIST.doThrowIf(count>NumberConstant.NUMBER_ZERO);
        //保存角色信息
        baseMapper.updateById(r);
        //先删除权限绑定关系 再保存
        List<Integer> priortys = vo.getPriorityIds();
        if(priortys!=null&&priortys.size()>NumberConstant.NUMBER_ZERO){
            rolePriorityRelationshipMapper.delete(
                    Wrappers.<RolePriorityRelationship>lambdaQuery()
                            .eq(RolePriorityRelationship::getRoleId,r.getId())
            );
            //保存角色权限绑定关系
            savePrioirs(priortys,r.getId());
        }

    }

    /**
     * 删除角色信息
     * @param ids 主键id
     * @param username 用户名
     */
    @Override
    public void delete(String ids, String username) {
        ExceptionEnum.FAIL_ID_NULL.doThrowIf(ids==null);
        String[] sps = ids.split(",");
        Arrays.stream(sps).forEach(id->{
            Role r = baseMapper.selectById(id);
            ExceptionEnum.FAIL_NULL.doThrowIf(r==null);
            //角色是否启用
            if(r.getStatus()== StatusEnum.STATUS_YES.getCode()) {
                throw new BaseException(new IResponseRxceptionCode(ResultEnum.FAIL.getCode(), StrUtil.format(ExceptionEnum.FAIL_STATUS_ROLES.getMessage(),r.getRoleName())));
            }
            //角色是否绑定到用户
            int count = accountRoleRelationshipMapper.selectCount(
                    Wrappers.<AccountRoleRelationship>lambdaQuery()
                            .eq(AccountRoleRelationship::getRoleId,id));
            if(count>NumberConstant.NUMBER_ZERO){
                throw new BaseException(new IResponseRxceptionCode(ResultEnum.FAIL.getCode(), StrUtil.format(ExceptionEnum.FAIL_BIND_USER.getMessage(),r.getRoleName())));
            }
            r.setIsDel(StatusEnum.STATUS_YES.getCode());
            r.setUpdateTime(LocalDateTime.now());
            r.setModifier(username);
            baseMapper.updateById(r);
        });
    }

    /**
     * 角色状态启用/停用
     * @param id 主键id
     * @param status 状态 (1启用，0.禁用)
     */
    @Override
    public void enableStatus(Long id, Integer status) {
        Role r = baseMapper.selectById(id);
        ExceptionEnum.FAIL_NULL.doThrowIf(r==null);
        r.setStatus(status);
        r.setUpdateTime(LocalDateTime.now());
        baseMapper.updateById(r);
    }

    /**
     * 对象转换 dto->do
     * @param vo
     * @return
     */
    private Role dto2Po(RoleDTO vo){
        Role r = null;
        try {
            r = vo.clone(Role.class);
        }catch (Exception e){
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return r;
    }

    /**
     * 对象转换 po->dto
     * @param po
     * @return
     */
    private RoleDTO po2Dto(Role po){
        RoleDTO r = null;
        try {
            r = po.clone(RoleDTO.class);
        }catch (Exception e){
            ExceptionEnum.FAIL_CHANGE.newException();
        }
        return r;
    }

    private void savePrioirs(List<Integer> priortys, Long id){
        //保存角色权限绑定关系
        priortys.stream().forEach(p ->{
            RolePriorityRelationship rp = new RolePriorityRelationship();
            rp.setCreateTime(LocalDateTime.now());
            rp.setUpdateTime(LocalDateTime.now());
            rp.setPriorityId(p);
            rp.setRoleId(id.intValue());
            rolePriorityRelationshipMapper.insert(rp);
        });
    }
}
